package cn.turboinfo.dongying.api.provider.admin.framework.shiro.credential;

import cn.turboinfo.dongying.api.entity.admin.exception.security.RateLimitReachedException;
import cn.turboinfo.dongying.api.provider.admin.component.security.RateLimitHelper;
import cn.turboinfo.dongying.api.provider.admin.component.security.RateLimitHelper;
import cn.turboinfo.dongying.api.provider.admin.framework.shiro.helper.PasswordHelper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;

import java.util.concurrent.TimeUnit;

@Slf4j
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {

    private final PasswordHelper passwordHelper;

    private final RateLimitHelper rateLimitHelper = new RateLimitHelper();

    public RetryLimitHashedCredentialsMatcher(PasswordHelper passwordHelper) {
        super(passwordHelper.getAlgorithmName());
        setHashIterations(passwordHelper.getHashIterations());
        setStoredCredentialsHexEncoded(true);
        this.passwordHelper = passwordHelper;
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        if (passwordHelper.getRetryLimit() > 0 && passwordHelper.getRetryPeriod() > 0) {
            // 如果设置了频率限制
            String username = (String) token.getPrincipal();
            synchronized (rateLimitHelper) {
                try {
                    rateLimitHelper.checkLimit("_rate_limit_login_" + username, passwordHelper.getRetryPeriod(), TimeUnit.MILLISECONDS, passwordHelper.getRetryLimit());
                    return super.doCredentialsMatch(token, info);
                } catch (RateLimitReachedException e) {
                    throw new RuntimeException("尝试登录次数超过频率限制");
                }
            }
        }
        return super.doCredentialsMatch(token, info);
    }
}
